//
//  PDFiumDocument+Merge.h
//  IAPDFKit
//
//  Created by macbook pro 2022 m2 on 2025/11/5.
//

#import "PDFiumDocument+Merge.h"
#import "fpdf_ppo.h"
#import "PDFiumFileWrite.h"

@implementation PDFiumDocument (Merge)


- (BOOL) mergeAllPagesToSinglePageVerticalWithOutputURL:(NSURL* _Nonnull)outputURL
                                            onProgress:(void (^_Nullable)(double))onProgress
                                           isCancelled:(BOOL (^_Nullable)(void))isCancelled {
    @autoreleasepool {
        if (!self.pdfiumDocumentRef || self.pageCount == 0) {
            return NO;
        }

        const double prepWeight = 0.9;

        float totalHeight = 0.f;
        float maxWidth = 0.f;
        for (int i = 0; i < self.pageCount; i++) {
            if (isCancelled && isCancelled()) {
                return NO;
            }
            FPDF_PAGE page = FPDF_LoadPage(self.pdfiumDocumentRef, i);
            if (!page) {
                continue;
            }

            float sourceWidth = (float)FPDF_GetPageWidthF(page);
            float sourceHeight = (float)FPDF_GetPageHeightF(page);
            
            totalHeight += sourceHeight;
            maxWidth = MAX(maxWidth, sourceWidth);

            FPDF_ClosePage(page);

            if (onProgress) {
                double frac = (double)(i + 1) / (double)self.pageCount;
                onProgress(prepWeight * frac);
            }
        }

        if (isCancelled && isCancelled()) {
            return NO;
        }

        FPDF_DOCUMENT mergedDoc = FPDF_ImportNPagesToOne(self.pdfiumDocumentRef,
                                                         maxWidth,
                                                         totalHeight,
                                                         1,
                                                         (size_t)self.pageCount);
        if (!mergedDoc) {
            return NO;
        }

        if (onProgress) {
            onProgress(prepWeight);
        }

        CustomFileWrite writer;
        writer.base.version = 1;
        writer.base.WriteBlock = FileWriteCallback;
        writer.file = fopen(outputURL.path.UTF8String, "wb");
        if (!writer.file) {
            FPDF_CloseDocument(mergedDoc);
            return NO;
        }

        if (isCancelled && isCancelled()) {
            fclose(writer.file);
            FPDF_CloseDocument(mergedDoc);
            return NO;
        }

        int ok = FPDF_SaveWithVersion(mergedDoc, &writer.base,
                                      FPDF_NO_INCREMENTAL | FPDF_REMOVE_SECURITY,
                                      17 /* PDF 1.7 */);

        fclose(writer.file);
        FPDF_CloseDocument(mergedDoc);

        if (onProgress) {
            onProgress(ok ? 1.0 : prepWeight);
        }

        return ok != 0;
    }
}

@end
